# coding=utf-8
# author='kungege21'
# date=2023/8/7 14:25
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException
from fastapi.params import Header

app05 = APIRouter()


"""FastAPI的依赖注入系统
    '依赖注入'是指在编程中，为保证代码运行成功，先导入或声明其所需要的‘依赖’，如子函数、数据库连接等。
    提高代码的复用率；
    共享数据库连接；
    增强安全、认证和角色管理；
"""

"""Dependencies 创建、导入和声明"""


async def common_paramters(q: Optional[str] = None,
                           page: int = 1,
                           limit: int = 10):
    return {'q': q, 'limit': limit}


@app05.get('/dependency01')
async def dependency01(commons: dict = Depends(common_paramters)):
    return commons


@app05.get('/dependency02')     # 依赖的调用不区分async
def dependency02(commons: dict = Depends(common_paramters)):
    return commons


"""Classes as Dependencies  类作为依赖项"""


class CommonQueryParams:
    def __init__(self, q: Optional[str] = None,
                 page: int = 1,
                 limit: int = 10):
        self.q = q
        self.page = page
        self.limit = limit


fake_items_db = [{'item_name': 'Foo'}, {'item_name': 'Col'}, {'item_name': 'Baz'}]


@app05.get('/class_as_dependencies')
# async def class_as_dependencies(commons: CommonQueryParams = Depends(CommonQueryParams)):
# async def class_as_dependencies(commons=Depends(CommonQueryParams)):
async def class_as_dependencies(commons: CommonQueryParams = Depends()):    # 三种用法效果一致
    response = {}
    if commons.q:
        response.update({'q': commons.q})
    items = fake_items_db[commons.page: commons.page + commons.limit]
    response.update({'item': items})
    return response


"""Sub-Dependencies  子依赖"""


def query(q: Optional[str] = None):
    return q


def sub_query(q: str = Depends(query), last_query: Optional[str] = None):
    if not q:
        return last_query
    return q


@app05.get('/sub_dependecy')
async def sub_denpendency(final_query: str = Depends(sub_query, use_cache=True)):
    """use_cache默认是True，表示当多个依赖有一个共同的子依赖时，每次request请求只会调用子依赖一次，下次从缓存中"""
    return {'sub_dependecy': final_query}


""" 路径操作函数中的依赖"""


async def verify_token(x_token: str = Header(...)):
    if x_token != 'fake-token':
        raise HTTPException(status_code=400, detail='X-Token header invalid')
    return x_token


async def verify_key(x_key: str = Header(...)):
    if x_key != 'fake-key':
        raise HTTPException(status_code=400, detail='X-Key header invalid')
    return x_key


@app05.get('/dependecy_in_path_operation', dependencies=[Depends(verify_key), Depends(verify_token)])
async def dependecy_in_path_operation():
    return [{'user': 'user01'}, {'user': 'user02'}]


"""见run.py 全局依赖"""

"""yied 依赖"""


async def get_db():
    db = 'Data Base Connect'
    try:
        yield db
    finally:
        end = db + " is Closed!"
        print(end)


@app05.get('/dependecy_with_yield')
async def dependecy_with_yield(con: str = Depends(get_db)):
    print(con)
    return {'DB': con}
